#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <termios.h>
#include <unistd.h>
#include <sys/stat.h>
#include <securec.h>
#include <pthread.h>
#include "bsl_uio.h"
#include "app_utils.h"
#include "app_errno.h"
#include "app_help.h"
#include "app_print.h"
#include "app_opt.h"
#include "app_provider.h"
#include "app_sm.h"
#include "app_keymgmt.h"
#include "bsl_sal.h"
#include "sal_file.h"
#include "ui_type.h"
#include "bsl_ui.h"
#include "bsl_errno.h"
#include "crypt_eal_rand.h"
#include "crypt_eal_kdf.h"
#include "crypt_algid.h"
#include "crypt_errno.h"
#include "crypt_params_key.h"
#include "app_speed.h"
#include "crypt_eal_cipher.h"
#include "crypt_eal_mac.h"
#include <sys/time.h>

//支持的加密算法列表
static const HITLS_CipherList g_cIdList[] = {
    {CRYPT_CIPHER_AES128_CBC, "aes-128-cbc"},
    {CRYPT_CIPHER_AES192_CBC, "aes-192-cbc"},
    {CRYPT_CIPHER_AES256_CBC, "aes-256-cbc"},
    {CRYPT_CIPHER_AES128_CTR, "aes-128-ctr"},
    {CRYPT_CIPHER_AES192_CTR, "aes-192-ctr"},
    {CRYPT_CIPHER_AES256_CTR, "aes-256-ctr"},
    {CRYPT_CIPHER_AES128_ECB, "aes-128-ecb"},
    {CRYPT_CIPHER_AES192_ECB, "aes-192-ecb"},
    {CRYPT_CIPHER_AES256_ECB, "aes-256-ecb"},
    {CRYPT_CIPHER_AES128_XTS, "aes-128-xts"},
    {CRYPT_CIPHER_AES256_XTS, "aes-256-xts"},
    {CRYPT_CIPHER_AES128_GCM, "aes-128-gcm"},
    {CRYPT_CIPHER_AES192_GCM, "aes-192-gcm"},
    {CRYPT_CIPHER_AES256_GCM, "aes-256-gcm"},
    {CRYPT_CIPHER_CHACHA20_POLY1305, "chacha20-poly1305"},
    {CRYPT_CIPHER_SM4_CBC, "sm4-cbc"},
    {CRYPT_CIPHER_SM4_ECB, "sm4-ecb"},
    {CRYPT_CIPHER_SM4_CTR, "sm4-ctr"},
    {CRYPT_CIPHER_SM4_GCM, "sm4-gcm"},
    {CRYPT_CIPHER_SM4_CFB, "sm4-cfb"},
    {CRYPT_CIPHER_SM4_OFB, "sm4-ofb"},
    {CRYPT_CIPHER_SM4_XTS, "sm4-xts"},
    {CRYPT_CIPHER_AES128_CFB, "aes128-cfb"},
    {CRYPT_CIPHER_AES192_CFB, "aes192-cfb"},
    {CRYPT_CIPHER_AES256_CFB, "aes256-cfb"},
    {CRYPT_CIPHER_AES128_OFB, "aes128-ofb"},
    {CRYPT_CIPHER_AES192_OFB, "aes192-ofb"},
    {CRYPT_CIPHER_AES256_OFB, "aes256-ofb"}
};

//支持的MAC算法列表
static const HITLS_MacList g_mIdList[] = {
    {CRYPT_MAC_HMAC_MD5, "md5"},
    {CRYPT_MAC_HMAC_SHA1, "sha1"},
    {CRYPT_MAC_HMAC_SHA224, "sha224"},
    {CRYPT_MAC_HMAC_SHA256, "sha256"},
    {CRYPT_MAC_HMAC_SHA384, "sha384"},
    {CRYPT_MAC_HMAC_SHA512, "sha512"},
    {CRYPT_MAC_HMAC_SM3, "sm3"},
    {CRYPT_MAC_HMAC_SHA3_224, "sha3-224"},
    {CRYPT_MAC_HMAC_SHA3_256, "sha3-256"},
    {CRYPT_MAC_HMAC_SHA3_384, "sha3-384"},
    {CRYPT_MAC_HMAC_SHA3_512, "sha3-512"}
};

//命令行选项类型枚举
typedef enum {
    HITLS_APP_OPT_CIPHER_ALG = 2,
    HITLS_APP_OPT_MAC,
    HITLS_APP_OPT_ENC,
    HITLS_APP_OPT_DEC,
    HITLS_APP_OPT_SECONDS,
    HITLS_APP_OPT_BYTES,
    HITLS_APP_OPT_AUTO_BLOCK,
    HITLS_APP_OPT_THREADS,  
} HITLS_OptType;

//命令行选项定义
static const HITLS_CmdOption g_speed_opts[] = {
    {"help",    HITLS_APP_OPT_HELP,    HITLS_APP_OPT_VALUETYPE_NO_VALUE,  "Display this function summary"},
    {"cipher",  HITLS_APP_OPT_CIPHER_ALG, HITLS_APP_OPT_VALUETYPE_STRING, "Cipher algorithm (e.g., aes-128-cbc)"},
    {"mac",      HITLS_APP_OPT_MAC, HITLS_APP_OPT_VALUETYPE_STRING, "MAC algorithm (e.g., sha256)"},
    {"enc",     HITLS_APP_OPT_ENC, HITLS_APP_OPT_VALUETYPE_NO_VALUE, "Encryption operation"},
    {"dec",     HITLS_APP_OPT_DEC, HITLS_APP_OPT_VALUETYPE_NO_VALUE, "Decryption operation"},
    {"seconds", HITLS_APP_OPT_SECONDS,  HITLS_APP_OPT_VALUETYPE_UINT, "Run benchmarks for N seconds (default: 3)"},
    {"bytes",   HITLS_APP_OPT_BYTES,    HITLS_APP_OPT_VALUETYPE_UINT, "Custom block size in bytes (e.g., 1024)"},
    {"auto-block", HITLS_APP_OPT_AUTO_BLOCK, HITLS_APP_OPT_VALUETYPE_NO_VALUE, "Auto test multiple block sizes (16/64/256/1024/8192/16384 bytes)"},
    {"threads", HITLS_APP_OPT_THREADS,  HITLS_APP_OPT_VALUETYPE_UINT, "Number of threads for parallel test"},
    {NULL}
};

//算法测试命令选项结构体
typedef struct {
    uint32_t version;
    int32_t cipherId;
    int32_t macId;
    int32_t encTag;
    int32_t seconds;
    int32_t bytes;
    bool autoBlock;
    int32_t threads;  
} SpeedCmdOpt;

//线程结构体
typedef struct {
    const SpeedCmdOpt* opt;       
    int block_size;               
    int thread_id;                
    uint64_t thread_ops;          
    size_t thread_total_bytes;    
    double thread_elapsed;        
} ThreadArgs;

static struct timeval start_timeval;                 //开始时间
double throughputs[TEST_BLOCK_SIZES_LEN] = { 0.0 };  //吞吐量数组

//函数声明汇总
static int32_t HandleOpt(SpeedCmdOpt* speed_Opt);
static void RunCipherBenchmark(const SpeedCmdOpt* opt);
static void RunCipherSingleBlockTest(const SpeedCmdOpt* opt, int block_size, int index);
static void RunCipherAutoBlockTest(const SpeedCmdOpt* opt);
static void* CipherThreadWork(void* arg);
static void RunMacBenchmark(const SpeedCmdOpt* opt);
static void RunMacSingleBlockTest(const SpeedCmdOpt* opt, int block_size, int index);
static void RunMacAutoBlockTest(const SpeedCmdOpt* opt);
static void* MacThreadWork(void* arg);
static void AggregateThreadResults(const SpeedCmdOpt* opt, ThreadArgs* args, double* total_speed, uint64_t* total_ops, double* total_elapsed);
static int32_t GetCipherId(const char* name);
static int32_t GetHMacId(const char* mdName);
static const char* GetCipherName(int32_t cipherId);
static const char* GetMacName(int32_t macId);
static void PrintCipherAlgList(void);
static void PrintHMacAlgList(void);
static void Time_F(int mode);
static bool CheckBlockSize(int cipherId, int block_size);


//主函数
int32_t HITLS_SpeedMain(int argc, char* argv[]) {
    int32_t Speedret = -1;
    
    //初始化命令选项 默认加密、单线程
    SpeedCmdOpt speedOpt = { 1, 0, 0, 1, 0, 0, 0, 1 };
    
    //初始化选项解析器
    Speedret = HITLS_APP_OptBegin(argc, argv, g_speed_opts);
    if (Speedret != HITLS_APP_SUCCESS) {
        AppPrintError("Failed to init option parser\n");
        goto End;
    }

    //处理命令行选项
    if ((Speedret = HandleOpt(&speedOpt)) != HITLS_APP_SUCCESS) {
        goto End;
    }

    //验证选项合法性
    if (speedOpt.seconds <= 0) {
        AppPrintError("Invalid seconds: %d (must be positive)\n", speedOpt.seconds);
        Speedret = HITLS_APP_OPT_VALUE_INVALID;
        goto End;
    }
    if (speedOpt.threads < 1 || speedOpt.threads > MAX_THREADS) {
        AppPrintError("Invalid thread count: %d (must be 1-%d)\n", speedOpt.threads, MAX_THREADS);
        Speedret = HITLS_APP_OPT_VALUE_INVALID;
        goto End;
    }
    if (speedOpt.bytes > 0 && speedOpt.cipherId != 0 && !CheckBlockSize(speedOpt.cipherId, speedOpt.bytes)) {
        AppPrintError("Block size %d is invalid for cipher %s\n", speedOpt.bytes, GetCipherName(speedOpt.cipherId));
        Speedret = HITLS_APP_OPT_VALUE_INVALID;
        goto End;
    }

    //开始测试
    if (speedOpt.cipherId != 0) {
        if (speedOpt.autoBlock || speedOpt.bytes == 0) {
            RunCipherAutoBlockTest(&speedOpt);
        }
        else {
            RunCipherBenchmark(&speedOpt);
        }
    }
    if (speedOpt.macId != 0) {
        if (speedOpt.autoBlock || speedOpt.bytes == 0) {
            RunMacAutoBlockTest(&speedOpt);
        }
        else {
            RunMacBenchmark(&speedOpt);
        }
    }

End:
    return Speedret;
}


//命令行选项处理函数
static int32_t HandleOpt(SpeedCmdOpt* speed_Opt) {
    int32_t opt_type;
    const char* val;
    speed_Opt->seconds = SECONDS;  //默认测试时长3s
    speed_Opt->threads = 1;        //默认单线程

    while ((opt_type = HITLS_APP_OptNext()) != HITLS_APP_OPT_EOF) {
        switch (opt_type) {
        case HITLS_APP_OPT_EOF:
            break;
        case HITLS_APP_OPT_ERR:
            AppPrintError("speed: Use -help for summary.\n");
            return HITLS_APP_OPT_UNKOWN;
        case HITLS_APP_OPT_HELP:
            HITLS_APP_OptHelpPrint(g_speed_opts);
            return HITLS_APP_HELP;
        case HITLS_APP_OPT_ENC:
            speed_Opt->encTag = 1;
            break;
        case HITLS_APP_OPT_DEC:
            speed_Opt->encTag = 0;
            break;
        case HITLS_APP_OPT_CIPHER_ALG:
            if ((speed_Opt->cipherId = GetCipherId(HITLS_APP_OptGetValueStr())) == -1) {
                return HITLS_APP_OPT_VALUE_INVALID;
            }
            break;
        case HITLS_APP_OPT_MAC:
            if ((speed_Opt->macId = GetHMacId(HITLS_APP_OptGetValueStr())) == -1) {
                return HITLS_APP_OPT_VALUE_INVALID;
            }
            break;
        case HITLS_APP_OPT_SECONDS:
            val = HITLS_APP_OptGetValueStr();
            if (val != NULL) speed_Opt->seconds = atoi(val);
            break;
        case HITLS_APP_OPT_BYTES:
            val = HITLS_APP_OptGetValueStr();
            if (val != NULL) speed_Opt->bytes = atoi(val);
            break;
        case HITLS_APP_OPT_AUTO_BLOCK:
            speed_Opt->autoBlock = true;
            break;
        case HITLS_APP_OPT_THREADS:
            val = HITLS_APP_OptGetValueStr();
            if (val != NULL) {
                speed_Opt->threads = atoi(val);
                if (speed_Opt->threads < 1) speed_Opt->threads = 1;
                if (speed_Opt->threads > MAX_THREADS) speed_Opt->threads = MAX_THREADS;
            }
            break;
        default:
            AppPrintError("Unknown option type: %d\n", opt_type);
            return HITLS_APP_OPT_UNKOWN;
        }
    }

    if (HITLS_APP_GetRestOptNum() != 0) {
        AppPrintError("Extra arguments given.\n");
        AppPrintError("enc: Use -help for summary.\n");
        return HITLS_APP_OPT_UNKOWN;
    }
    if (speed_Opt->cipherId == 0 && speed_Opt->macId == 0) {
        AppPrintError("Please specify either --cipher or --mac algorithm\n");
        return HITLS_APP_OPT_VALUE_INVALID;
    }

    return HITLS_APP_SUCCESS;
}

//指定块大小 加密算法测试入口
static void RunCipherBenchmark(const SpeedCmdOpt* opt) {
    printf("=== Cipher Custom Block Test: %s ===\n", GetCipherName(opt->cipherId));
    RunCipherSingleBlockTest(opt, opt->bytes, 0);
}

//单个块加密测试
static void RunCipherSingleBlockTest(const SpeedCmdOpt* opt, int block_size, int index) {
    int duration = (opt->seconds > 0) ? opt->seconds : SECONDS;
    bool is_enc = (opt->encTag == 1);
    const char* alg_name = GetCipherName(opt->cipherId);

    pthread_t* threads = (pthread_t*)malloc(sizeof(pthread_t) * opt->threads);
    ThreadArgs* thread_args = (ThreadArgs*)malloc(sizeof(ThreadArgs) * opt->threads);
    if (threads == NULL || thread_args == NULL) {
        AppPrintError("Failed to allocate memory for threads\n");
        free(threads);
        free(thread_args);
        throughputs[index] = 0.0;
        return;
    }

    for (int i = 0; i < opt->threads; i++) {
        thread_args[i].opt = opt;
        thread_args[i].block_size = block_size;
        thread_args[i].thread_id = i;
        thread_args[i].thread_ops = 0;
        thread_args[i].thread_total_bytes = 0;
        thread_args[i].thread_elapsed = 0.0;
    }

    Time_F(0);  
    for (int i = 0; i < opt->threads; i++) {
        if (pthread_create(&threads[i], NULL, CipherThreadWork, &thread_args[i]) != 0) {
            AppPrintError("Failed to create cipher thread %d\n", i);
            for (int j = 0; j < i; j++) pthread_join(threads[j], NULL);
            free(threads);
            free(thread_args);
            throughputs[index] = 0.0;
            return;
        }
    }

    for (int i = 0; i < opt->threads; i++) {
        pthread_join(threads[i], NULL);
    }

    double total_speed = 0.0;
    uint64_t total_ops = 0;
    double total_elapsed = 0.0;
    AggregateThreadResults(opt, thread_args, &total_speed, &total_ops, &total_elapsed);

    printf("Doing %s %s for %.1fs on %d size blocks: %llu %s's in %.2fs ", is_enc ? "Encryption" : "Decryption", alg_name, (double)duration, block_size, (unsigned long long)total_ops, alg_name, total_elapsed);
    printf("speed=%.2f KB/s (%.2f MB/s)\n", total_speed, total_speed / 1024.0);

    throughputs[index] = total_speed;

    free(threads);
    free(thread_args);
}

//所有块加密测试入口
static void RunCipherAutoBlockTest(const SpeedCmdOpt* opt) {
    printf("=== Cipher Auto Block Test: %s ===\n", GetCipherName(opt->cipherId));
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        int block_size = TEST_BLOCK_SIZES[i];
        RunCipherSingleBlockTest(opt, block_size, i);
    }

    printf("=== Cipher Performance Summary (units: KB/s) ===\n");
    printf("%-15s", "Algorithm");
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        printf("%-15d", TEST_BLOCK_SIZES[i]);
    }
    printf("\n%-15s", GetCipherName(opt->cipherId));
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        printf("%-15.2f", throughputs[i]);
    }
    printf("\n");
}

//加密线程函数
static void* CipherThreadWork(void* arg) {
    ThreadArgs* args = (ThreadArgs*)arg;
    const SpeedCmdOpt* opt = args->opt;
    int block_size = args->block_size;
    int thread_id = args->thread_id;
    int duration = (opt->seconds > 0) ? opt->seconds : SECONDS;
    bool is_enc = (opt->encTag == 1);

    unsigned char key[MAX_KEY_LEN] = { 0 };
    unsigned char iv[16] = { 0 };
    unsigned char* in = malloc(block_size);
    unsigned char* out = malloc(block_size + 32);
    CRYPT_EAL_CipherCtx* ctx = NULL;
    if (in == NULL || out == NULL) {
        AppPrintError("Thread %d: Failed to allocate memory\n", thread_id);
        goto End;
    }
    memset(in, 0xAA, block_size);

    int keyLen = 16;
    switch (opt->cipherId) {
    case CRYPT_CIPHER_AES128_CBC: case CRYPT_CIPHER_AES128_CTR:
    case CRYPT_CIPHER_AES128_ECB: case CRYPT_CIPHER_AES128_GCM:
    case CRYPT_CIPHER_AES128_CFB: case CRYPT_CIPHER_AES128_OFB:
    case CRYPT_CIPHER_SM4_CBC: case CRYPT_CIPHER_SM4_ECB:
    case CRYPT_CIPHER_SM4_CTR: case CRYPT_CIPHER_SM4_GCM:
    case CRYPT_CIPHER_SM4_CFB: case CRYPT_CIPHER_SM4_OFB:
        keyLen = 16;
        break;
    case CRYPT_CIPHER_AES192_CBC: case CRYPT_CIPHER_AES192_CTR:
    case CRYPT_CIPHER_AES192_ECB: case CRYPT_CIPHER_AES192_GCM:
    case CRYPT_CIPHER_AES192_CFB: case CRYPT_CIPHER_AES192_OFB:
        keyLen = 24;
        break;
    case CRYPT_CIPHER_AES256_CBC: case CRYPT_CIPHER_AES256_CTR:
    case CRYPT_CIPHER_AES256_ECB: case CRYPT_CIPHER_AES256_GCM:
    case CRYPT_CIPHER_AES256_CFB: case CRYPT_CIPHER_AES256_OFB:
        keyLen = 32;
        break;
    case CRYPT_CIPHER_AES128_XTS:
        keyLen = 32;
        break;
    case CRYPT_CIPHER_AES256_XTS:
        keyLen = 64;
        break;
    default:
        keyLen = 16;
        break;
    }

    ctx = CRYPT_EAL_CipherNewCtx(opt->cipherId);
    if (ctx == NULL) {
        AppPrintError("Thread %d: Failed to create cipher ctx\n", thread_id);
        goto End;
    }
    if (CRYPT_EAL_CipherInit(ctx, key, keyLen, iv, sizeof(iv), is_enc) != CRYPT_SUCCESS) {
        AppPrintError("Thread %d: Cipher init failed (alg: %s, keyLen: %d)\n", thread_id, GetCipherName(opt->cipherId), keyLen);
        goto End;
    }

    struct timeval thread_start;
    gettimeofday(&thread_start, NULL);
    uint64_t thread_ops = 0;
    size_t thread_total_bytes = 0;

    while (1) {
        struct timeval current;
        gettimeofday(&current, NULL);
        double elapsed = (current.tv_sec - thread_start.tv_sec) + (current.tv_usec - thread_start.tv_usec) / 1000000.0;
        if (elapsed >= duration) break;

        uint32_t outlen = block_size + 32;
        if (CRYPT_EAL_CipherUpdate(ctx, in, block_size, out, &outlen) != CRYPT_SUCCESS) {
            AppPrintError("Thread %d: Cipher update failed (block size: %d)\n", thread_id, block_size);
            break;
        }

        thread_ops++;
        thread_total_bytes += block_size;
    }

    struct timeval thread_end;
    gettimeofday(&thread_end, NULL);
    args->thread_ops = thread_ops;
    args->thread_total_bytes = thread_total_bytes;
    args->thread_elapsed = (thread_end.tv_sec - thread_start.tv_sec) + (thread_end.tv_usec - thread_start.tv_usec) / 1000000.0;

End:
    if (key != NULL) memset_s(key, MAX_KEY_LEN, 0, MAX_KEY_LEN);
    if (iv != NULL) memset_s(iv, sizeof(iv), 0, sizeof(iv));
    if (ctx != NULL) CRYPT_EAL_CipherFreeCtx(ctx);
    if (in != NULL) free(in);
    if (out != NULL) free(out);
    return NULL;
}

//指定块大小 MAC算法测试入口
static void RunMacBenchmark(const SpeedCmdOpt* opt) {
    printf("=== MAC Custom Block Test: %s ===\n", GetMacName(opt->macId));
    RunMacSingleBlockTest(opt, opt->bytes, 0);
}

//单个块MAC测试
static void RunMacSingleBlockTest(const SpeedCmdOpt* opt, int block_size, int index) {
    int duration = (opt->seconds > 0) ? opt->seconds : SECONDS;
    const char* alg_name = GetMacName(opt->macId);

    pthread_t* threads = (pthread_t*)malloc(sizeof(pthread_t) * opt->threads);
    ThreadArgs* thread_args = (ThreadArgs*)malloc(sizeof(ThreadArgs) * opt->threads);
    if (threads == NULL || thread_args == NULL) {
        AppPrintError("Failed to allocate memory for threads\n");
        free(threads);
        free(thread_args);
        throughputs[index] = 0.0;
        return;
    }

    for (int i = 0; i < opt->threads; i++) {
        thread_args[i].opt = opt;
        thread_args[i].block_size = block_size;
        thread_args[i].thread_id = i;
        thread_args[i].thread_ops = 0;
        thread_args[i].thread_total_bytes = 0;
        thread_args[i].thread_elapsed = 0.0;
    }

    Time_F(0);  
    for (int i = 0; i < opt->threads; i++) {
        if (pthread_create(&threads[i], NULL, MacThreadWork, &thread_args[i]) != 0) {
            AppPrintError("Failed to create MAC thread %d\n", i);
            for (int j = 0; j < i; j++) pthread_join(threads[j], NULL);
            free(threads);
            free(thread_args);
            throughputs[index] = 0.0;
            return;
        }
    }

    for (int i = 0; i < opt->threads; i++) {
        pthread_join(threads[i], NULL);
    }

    double total_speed = 0.0;
    uint64_t total_ops = 0;
    double total_elapsed = 0.0;
    AggregateThreadResults(opt, thread_args, &total_speed, &total_ops, &total_elapsed);

    printf("Doing %s for %.1fs on %d size blocks: %llu %s's in %.2fs ", alg_name, (double)duration, block_size, (unsigned long long)total_ops, alg_name, total_elapsed);
    printf("speed=%.2f KB/s (%.2f MB/s)\n", total_speed, total_speed / 1024.0);

    throughputs[index] = total_speed;

    free(threads);
    free(thread_args);
}

//所有块MAC测试入口
static void RunMacAutoBlockTest(const SpeedCmdOpt* opt) {
    printf("=== MAC Auto Block Test: %s ===\n", GetMacName(opt->macId));
    int block_size = 0;
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        block_size = TEST_BLOCK_SIZES[i];
        RunMacSingleBlockTest(opt, block_size, i);
    }

    printf("=== MAC Performance Summary (units: KB/s) ===\n");
    printf("%-15s", "Algorithm");
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        printf("%-15d", TEST_BLOCK_SIZES[i]);
    }
    printf("\n");
    printf("%-15s", GetMacName(opt->macId));
    for (int i = 0; i < TEST_BLOCK_SIZES_LEN; i++) {
        printf("%-15.2f", throughputs[i]);
    }
    printf("\n");
}

//MAC线程函数
static void* MacThreadWork(void* arg) {
    ThreadArgs* args = (ThreadArgs*)arg;
    const SpeedCmdOpt* opt = args->opt;
    int block_size = args->block_size;
    int thread_id = args->thread_id;
    int duration = (opt->seconds > 0) ? opt->seconds : SECONDS;

    unsigned char key[MAX_KEY_LEN] = { 0 };
    unsigned char mac[MAX_MAC_LEN] = { 0 };
    unsigned char* data = malloc(block_size);
    CRYPT_EAL_MacCtx* ctx = NULL;
    if (data == NULL) {
        AppPrintError("Thread %d: Failed to allocate memory for MAC test\n", thread_id);
        goto End;
    }
    memset(data, 0xAA, block_size);

    uint32_t keyLen = 32;
    switch (opt->macId) {
    case CRYPT_MAC_HMAC_SHA1:
    case CRYPT_MAC_HMAC_SHA224:
    case CRYPT_MAC_HMAC_SHA256:
    case CRYPT_MAC_HMAC_SM3:
        keyLen = 32;
        break;
    case CRYPT_MAC_HMAC_SHA384:
    case CRYPT_MAC_HMAC_SHA512:
        keyLen = 64;
        break;
    default:
        keyLen = 32;
        break;
    }

    ctx = CRYPT_EAL_MacNewCtx(opt->macId);
    if (ctx == NULL) {
        AppPrintError("Thread %d: Failed to create MAC ctx\n", thread_id);
        goto End;
    }
    if (CRYPT_EAL_MacInit(ctx, key, keyLen) != CRYPT_SUCCESS) {
        AppPrintError("Thread %d: MAC init failed\n", thread_id);
        goto End;
    }

    struct timeval thread_start;
    gettimeofday(&thread_start, NULL);
    uint64_t thread_ops = 0;
    size_t thread_total_bytes = 0;

    while (1) {
        struct timeval current;
        gettimeofday(&current, NULL);
        double elapsed = (current.tv_sec - thread_start.tv_sec) + (current.tv_usec - thread_start.tv_usec) / 1000000.0;
        if (elapsed >= duration) break;

        if (CRYPT_EAL_MacUpdate(ctx, data, block_size) != CRYPT_SUCCESS) {
            AppPrintError("Thread %d: MAC update failed\n", thread_id);
            break;
        }

        thread_ops++;
        thread_total_bytes += block_size;
    }
    uint32_t macLen = sizeof(mac);
    if (CRYPT_EAL_MacFinal(ctx, mac, &macLen) != CRYPT_SUCCESS) {
        AppPrintError("Thread %d: MAC final failed\n", thread_id);
        goto End;
    }

    struct timeval thread_end;
    gettimeofday(&thread_end, NULL);
    args->thread_ops = thread_ops;
    args->thread_total_bytes = thread_total_bytes;
    args->thread_elapsed = (thread_end.tv_sec - thread_start.tv_sec) + (thread_end.tv_usec - thread_start.tv_usec) / 1000000.0;

End:
    if (key != NULL) memset_s(key, MAX_KEY_LEN, 0, MAX_KEY_LEN);
    if (mac != NULL) memset_s(mac, sizeof(mac), 0, sizeof(mac));
    if (ctx != NULL) CRYPT_EAL_MacFreeCtx(ctx);
    if (data != NULL) free(data);
    return NULL;
}

//汇总所有线程结果 计算总吞吐量、总操作次数、总耗时
static void AggregateThreadResults(const SpeedCmdOpt* opt, ThreadArgs* args, double* total_speed, uint64_t* total_ops, double* total_elapsed) {
    *total_ops = 0;
    size_t total_bytes = 0;
    *total_elapsed = 0.0;

    for (int i = 0; i < opt->threads; i++) {
        *total_ops += args[i].thread_ops;
        total_bytes += args[i].thread_total_bytes;
        if (args[i].thread_elapsed > *total_elapsed) {
            *total_elapsed = args[i].thread_elapsed;
        }
    }

    if (*total_elapsed <= 0.0001) *total_elapsed = 0.0001;  
    *total_speed = (total_bytes / 1024.0) / *total_elapsed;
}

//根据加密算法名称获取加密算法ID
static int32_t GetCipherId(const char* name) {
    for (size_t i = 0; i < sizeof(g_cIdList) / sizeof(g_cIdList[0]); i++) {
        if (strcmp(g_cIdList[i].cipherAlgName, name) == 0) {
            return g_cIdList[i].cipherId;
        }
    }
    PrintCipherAlgList();
    return -1;
}

//根据MAC算法名称获取MAC算法ID
static int32_t GetHMacId(const char* mdName) {
    for (size_t i = 0; i < sizeof(g_mIdList) / sizeof(g_mIdList[0]); i++) {
        if (strcmp(g_mIdList[i].macAlgName, mdName) == 0) {
            return g_mIdList[i].macId;
        }
    }
    PrintHMacAlgList();
    return -1;
}

//根据加密算法ID获取加密算法名称
static const char* GetCipherName(int32_t cipherId) {
    for (size_t i = 0; i < sizeof(g_cIdList) / sizeof(g_cIdList[0]); i++) {
        if (g_cIdList[i].cipherId == cipherId) {
            return g_cIdList[i].cipherAlgName;
        }
    }
    return "unknown_cipher";
}

//根据MAC算法ID获取MAC算法名称
static const char* GetMacName(int32_t macId) {
    for (size_t i = 0; i < sizeof(g_mIdList) / sizeof(g_mIdList[0]); i++) {
        if (g_mIdList[i].macId == macId) {
            return g_mIdList[i].macAlgName;
        }
    }
    return "unknown_mac";
}

//打印支持的加密算法列表
static void PrintCipherAlgList(void) {
    AppPrintError("The current version supports only the following cipher algorithms:\n");
    for (size_t i = 0; i < sizeof(g_cIdList) / sizeof(g_cIdList[0]); i++) {
        AppPrintError("%-19s", g_cIdList[i].cipherAlgName);
        if ((i + 1) % 4 == 0 && i != sizeof(g_cIdList) - 1) {
            AppPrintError("\n");
        }
    }
    AppPrintError("\n");
}

//打印支持的MAC算法列表
static void PrintHMacAlgList(void) {
    AppPrintError("The current version supports only the following digest algorithms:\n");
    for (size_t i = 0; i < sizeof(g_mIdList) / sizeof(g_mIdList[0]); i++) {
        AppPrintError("%-19s", g_mIdList[i].macAlgName);
        if ((i + 1) % 4 == 0 && i != sizeof(g_mIdList) - 1) {
            AppPrintError("\n");
        }
    }
    AppPrintError("\n");
}

//记录开始时间
static void Time_F(int mode) {
    if (mode == 0) {
        gettimeofday(&start_timeval, NULL);
    }
}

//块大小合法性检验
static bool CheckBlockSize(int cipherId, int block_size) {
    switch (cipherId) {
    case CRYPT_CIPHER_AES128_CBC: case CRYPT_CIPHER_AES192_CBC:
    case CRYPT_CIPHER_AES256_CBC: case CRYPT_CIPHER_SM4_CBC:
    case CRYPT_CIPHER_AES128_ECB: case CRYPT_CIPHER_SM4_ECB:
        return (block_size % 16) == 0;
    default:
        return block_size > 0;
    }
}